//#include <stdio.h>

/*int main (int argc, const char * argv[]) {
 // insert code here...
 printf("Hello, World!\n");
 return 0;
 }*/

// pt3toitwinconv.cpp : Defines the entry point for the console application.
//


//int _tmain(int argc, _TCHAR* argv[]) {	return 0;}

/* =============================
 File: "pt3_it.c"
 Compiler: Turbo C 2.0
 ============================= */

/* ѕри компил€ции параметр "Options > Compiler > Optimization > Jump
 optimization" должен быть выключен ("Off"). */

/* ѕрограмму надо компилировать в Turbo C 2.0, а не в 2.01, так как
 при компил€ции в Turbo C 2.01 про€вл€етс€ ошибка: печать числа со знаком,
 если указан формат вывода %+03d, происходит неправильно: если число
 отрицательное, оно будет занимать на символ больше, чем надо (после
 знака печатаетс€ дополнительный 0). “аким образом, текстовый файл,
 сформированный программой, будет выгл€деть не лучшим образом.   тому же
 после компил€ции в Turbo C 2.01 исполн€емый файл будет длиннее. */

//#include <stdafx.h>
#include <unistd.h>
#include <stdio.h>
//#include <io.h>
//#include <dir.h>
#include <STDLIB.H>
//#include <direct.h>
#include <string.h>

#define byte unsigned char    /* 1 байт.  */
//#define byte char    /* 1 байт.  */
//#define word unsigned int     /* 2 байта. */
#define word unsigned short    /* 2 байта. */
#define strnicmp strncasecmp  

/* ========================== ќписание функций =========================== */

void make_it (char* name);
void make_txt (char* name);
void move_32bytes (byte* src, byte* dst);
byte getb_pt3 (word a);
void clear_p ();
byte convert_p (word a, byte c);
void out_p (byte p_rows, FILE* f);

FILE* fopen_1 (char* name, char* mode);
void fclose_1 (FILE* f);
void fputc_1 (int c, FILE* f);
void fgetpos_1 (FILE* f, fpos_t* pos);
void fsetpos_1 (FILE* f, fpos_t* pos);
void r_err ();
void w_err ();
void pt3_err ();
void vol_err ();
int set_dir (char *s, char *name);
int cmp_names (char* s1, char* s2);

/* ==================== ќписание констант и структур ===================== */

#define MIN_PT3_LEN 216      /* ћинимальна€ длина pt3-модул€. */
#define MAX_PT3_LEN 0x4000   /* ћаксимальна€ длина pt3-модул€. */

struct channel     /* ƒанные об одном канале в строке паттерна. */
{
	byte note;        /* Ќомер ноты: 0 - нет, 1-96 - ноты C-1...B-8, 255 - R. */
	byte sample;      /* Ќомер сэмпла, 0 - нет. */
	byte env_type;    /* “ип огибающей. */
	byte orn;         /* Ќомер орнамента, 0 - нет. */
	byte volume;      /* √ромкость, 0 - нет. */
	byte command[4];  /*  оманда (4 байта), первый байт=0 - нет команды. */
};

struct patt_line   /* ќдна строка паттерна. */
{
	word env;                  /* ѕериод огибающей (0 - нет). */
	byte noise;                /* —мещение шума. */
	struct channel channel[3]; /*  аналы A,B,C. */
};

/* ======================== √лобальные переменные ======================== */

struct patt_line pattern[64];  /* Ѕуфер дл€ хранени€ одного паттерна. */
byte module_pt3[MAX_PT3_LEN];  /* Ѕуфер дл€ хранени€ исходного pt3-модул€. */
long len_pt3;                  /* ƒлина исходного pt3-модул€. */
byte name_pt3[33];             /* Ќазвание pt3-модул€. */
byte author_pt3[33];           /* јвтор pt3-модул€. */
byte pt3_id;                   /* 0 - модуль создан в PT3, 1 - в VTII. */
int  song_len;                 /* ƒлина списка позиций pt3-модул€. */
byte song_loop;                /* ѕозици€ начала зацикливани€ pt3-модул€. */
byte max_used_p=0;             /* Ќаибольший номер используемого паттерна
 (без учЄта возможного добавлени€ паттерна
 из-за зацикливани€ модул€). */
byte used_p[85];               /* ƒл€ каждого паттерна от 0 до 84: 0 - не
 используетс€, 1 - используетс€. */
byte order[256];               /* —писок позиций (без учЄта возможного
 изменени€ номера последнего паттерна
 из-за зацикливани€ модул€). */
byte p_rows;                   /*  оличество строк в текущем паттерне. */
byte add_pattern=0;            /* Ќадо ли добавл€ть дополнительный паттерн
 из-за зацикливани€? */

byte module_it[0xC0]=      /* ѕервые 0xC0 байтов формируемого it-модул€. */
{
'I','M','P','M',
0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,   /* Ќазвание (26 байтов, включа€ */
0,0,0,0,0, 0,0,0,0,0, 0,           /* последний 0). */
4,0x10,                            /* PHiligt. */
0,0,                               /*  ол-во позиций+1. */
0,0,                               /*  ол-во инструментов (0). */
0,0,                               /*  ол-во сэмплов (0). */
0,0,                               /*  ол-во паттернов. */
0x17,2,                            /* Cwt/v */
0x14,2,                            /* Cmwt */
0xD,0,                             /* Flags */
7,0,                               /* Special */
0x80,                              /* GV */
0x30,                              /* MV */
0,                                 /* Initial Speed */
125,                               /* Initial Tempo */
0x80,                              /* Sep */
0,                                 /* PWD */
0,0,                               /* Message Length */
0,0,0,0,                           /* Message Offset */
0x4E,0xAF,0x09,0xE4,               /* Reserved */
32,32,32,32,32,32,32,32,           /* Chnl Pan */
32,32,32,32,32,32,32,32,
32,32,32,32,32,32,32,32,
32,32,32,32,32,32,32,32,
32,32,32,32,32,32,32,32,
32,32,32,32,32,32,32,32,
32,32,32,32,32,32,32,32,
32,32,32,32,32,32,32,32,
64,64,64,64,64,64,64,64,           /* Chnl Vol */
64,64,64,64,64,64,64,64,
64,64,64,64,64,64,64,64,
64,64,64,64,64,64,64,64,
64,64,64,64,64,64,64,64,
64,64,64,64,64,64,64,64,
64,64,64,64,64,64,64,64,
64,64,64,64,64,64,64,64,
};

char cur_path[129];        /*  аталог, из которого запущена программа. */
FILE *f_pt3;               /* »сходный pt3-файл. */
FILE *f_it;                /* ‘ормируемый it-файл. */
FILE *f_txt;               /* ‘ормируемый текстовый файл. */
unsigned int vol_tab[16]=  /* “аблица громкости. */
{0,0,0,1,1,2,2,4,5,8,11,16,22,32,45,64};
int vt_used=0;             /* ѕри запуске была задана таблица громкости. */
word a;                    /* —мещение в pt3-модуле. */
int i,j,k;

/* ======================== ѕошла сама программа ========================= */

int main (int argc, char *argv[])
{
	printf ("sizeof(char) %d \n",sizeof(char));
	printf ("sizeof(unsigned short) %d \n",sizeof(unsigned short));	
	printf ("sizeof(int) %d \n",sizeof(int));
	printf ("sizeof(unsigned int) %d \n",sizeof(unsigned int));	
	printf ("\n\
			г======================================================================ђ\n\
			¶                             PT3_IT 1.01                              ¶\n\
			¶----------------------------------------------------------------------¶\n\
			¶ Music convertor: Pro Tracker 3 (ZX Spectrum) -> Impulse Tracker (PC) ¶\n\
			¶ (c) Ivan Roshin, Moscow, 25 Dec 2004                                 ¶\n\
			¶ E-mail: bestview@mtu-net.ru                WWW: http://www.ivr.da.ru ¶\n\
			L======================================================================-\n\n");
	
	if ((argc>=2)&&(strnicmp(argv[1],"/v",(size_t)2)==0))
	{           /* «адана таблица громкости. */
		vt_used=1;
		/* «амен€ем зап€тые в строке на пробелы. */
		for (i=0;i<strlen(argv[1]);i++) {if (argv[1][i]==',') argv[1][i]=' ';}
		/* „итаем значени€. */
		if (sscanf(argv[1]+2,"%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u",
				   vol_tab+1,vol_tab+2,vol_tab+3,vol_tab+4,vol_tab+5,
				   vol_tab+6,vol_tab+7,vol_tab+8,vol_tab+9,vol_tab+10,
				   vol_tab+11,vol_tab+12,vol_tab+13,vol_tab+14,vol_tab+15)!=15)
			vol_err();
		/* Ќи одно из значений не должно превышать 64. */
		for (i=1;i<=15;i++) {if (vol_tab[i]>64) vol_err();}
	}
	
	if ((argc<3+vt_used)||(argc>4+vt_used))
	{
		printf ("\
				Syntax: pt3_it.exe {options} pt3-file it-file {text-file}\n\n\
				Options:\n\n\
				/vN1,N2,...,N15 - define table for converting volume in patterns\n\
				(each value from 0 to 64).\n\n");
		exit(1);
	}
	
	if (getcwd(cur_path,128)==NULL)
	{
		printf ("Error: can't get current directory!\n\n");
		exit (1);
	}
	
/*	if (cmp_names(argv[1+vt_used],argv[2+vt_used])==0)
	{
		printf ("Error: pt3-file=it-file!\n\n");
		exit (1);
	}
	
	if ((argc==4+vt_used)&&(cmp_names(argv[1+vt_used],argv[3+vt_used])==0))
	{
		printf ("Error: pt3-file=txt-file!\n\n");
		exit (1);
	}
	if ((argc==4+vt_used)&&(cmp_names(argv[2+vt_used],argv[3+vt_used])==0))
	{
		printf ("Error: it-file=txt-file!\n\n");
		exit (1);
	}*/
	
	printf ("Converting: %s  ",argv[1+vt_used]);
	
	/* „итаем исходный pt3-файл в буфер, предварительно проверив, чтобы длина
	 файла была допустимой. */
	
	f_pt3=fopen_1(argv[1+vt_used],"rb");
	len_pt3=16000;
//	len_pt3=filelength(fileno(f_pt3));
	fseek (f_pt3 , 0 , SEEK_END);
	len_pt3 = ftell (f_pt3);
	rewind (f_pt3);
	
	if ((len_pt3<MIN_PT3_LEN)||(len_pt3>MAX_PT3_LEN)) pt3_err();
//	if (fread(module_pt3,(size_t)len_pt3,(size_t)1,f_pt3)!=1) r_err();
	
//  В макоси параметры длины всего файла и его элемента переставлены!	
	size_t result;
	result = fread(module_pt3,1,(size_t)len_pt3,f_pt3);
	if (result != len_pt3 ) {
		r_err();	
	}
	fclose_1(f_pt3);
	
	/* ѕровер€ем строку-идентификатор в начале pt3-модул€ и устанавливаем
	 pt3_id. */
	
	if (memcmp(module_pt3,"ProTracker 3",(size_t)12)==0) pt3_id=0;
	else
	{
		if (memcmp(module_pt3,"Vortex Tracker II",(size_t)17)==0) pt3_id=1;
		else pt3_err();
	}
	
	/* ѕолучаем строки с названием pt3-модул€ и сведени€ми об авторе. */
	
	move_32bytes (module_pt3+30,name_pt3);
	move_32bytes (module_pt3+66,author_pt3);
	
	/* ѕолучаем song_len, song_loop, order и признаки используемости дл€
	 паттернов. ќпредел€ем, надо ли добавл€ть дополнительный паттерн из-за
	 зацикливани€ (признак add_pattern). Ќадо, если последний паттерн в списке
	 позиций уже встречалс€ ранее. */
	
	/* ≈сли программа будет обрабатывать несколько модулей, то перед обработкой
	 очередного модул€ необходимо обнулить max_used_p и массив used_p. */
	
	song_len=getb_pt3(101); if (song_len==0) song_len=256;
	song_loop=getb_pt3(102);
	
	for (i=0;i<song_len;i++)
	{
		byte b=getb_pt3(201+i)/3;
		if (b==85) break;   /* “.е. байт был равен 255 - признак конца списка. */
		order[i]=b;
		add_pattern=used_p[b];
		used_p[b]=1;
		if (b>max_used_p) max_used_p=b;
	}
	
	make_it (argv[2+vt_used]);                       /* ‘ормируем it-файл. */
	if (argc==4+vt_used) make_txt (argv[3+vt_used]); /* ≈сли надо, формируем */
	/* txt-файл. */
//	make_txt (argv[2+vt_used]);
	printf ("OK\n\n");
	exit (0);
}

/* ==========================================================================
 ‘ункци€ make_it - формирование it-файла.
 ¬ход: name - им€ файла.
 ========================================================================= */

void make_it (char* name)
{
	fpos_t p_offset;    /* —мещение, по которому надо записать смещение
	 текущего записываемого паттерна. */
	
	f_it=fopen_1(name,"wb");
	
	/* Ќазвание модул€. */
	
	sprintf(module_it+4,"%.25s",name_pt3);
	
	/* ƒлина списка (включа€ завершающий байт 255). */
	
	{
		word a=song_len+1;
		module_it[0x20]=a;
		module_it[0x21]=a>>8;
	}
	
	/*  оличество паттернов (max_used_p+1+add_pattern). */
	
	{
		word a=max_used_p+1+add_pattern;
		module_it[0x26]=a;
		module_it[0x27]=a>>8;
	}
	
	/* Initial Speed */    /* ¬ pt3-модуле tempo не может быть 0! */
	
	if ((module_it[0x32]=getb_pt3(100))==0) pt3_err();
	
	/* «аписываем начало модул€. */
	
	if (fwrite(module_it,(size_t)0xC0,(size_t)1,f_it)!=1) w_err();
	
	/* ¬ыводим позиции. */
	
	for (i=0;i<song_len-1;i++)  /* ¬се, за исключением последней. */
	{
		fputc_1 (order[i],f_it);
	}
	/* ¬ последней позиции - дополнительный паттерн с номером max_used_p+1, если
	 add_pattern=1. »наче - как есть. */
	if (add_pattern==1) fputc_1 (max_used_p+1,f_it);
	else fputc_1 (order[i],f_it);
	/* » завершающий байт 255. */
	fputc_1 (255,f_it);
	
	/* ¬ыводим смещени€ до паттернов - пока нулевые. */
	
	fgetpos_1 (f_it,&p_offset);
	for (i=0;i<max_used_p+1+add_pattern;i++)
	{
		fputc_1 (0,f_it);
		fputc_1 (0,f_it);
		fputc_1 (0,f_it);
		fputc_1 (0,f_it);
	}
	
	/* “еперь знаем смещение Message. «аписываем его в нужное место. */
	
	{
		fpos_t a;          /* —мещение Message. */
		fpos_t b=0x38;     /* —мещение, по которому записываем смещение Message. */
		fpos_t c;          /* —мещение первого байта после Message. */
		fpos_t d=0x36;     /* —мещение, по которому записываем длину Message. */
		
		fgetpos_1 (f_it,&a);
		fsetpos_1 (f_it,&b);
		fputc_1 (a,f_it);
		fputc_1 (a>>8,f_it);
		fsetpos_1 (f_it,&a);
		
		/* «аписываем текст Message. */
		
		if (fprintf(f_it,"Music: %s\r   by: %s%c",name_pt3,author_pt3,0)==EOF)
			w_err();
		fgetpos_1 (f_it,&c);
		fsetpos_1 (f_it,&d);
		fputc_1 (c-a,f_it);
		fputc_1 ((c-a)>>8,f_it);
		fsetpos_1 (f_it,&c);
	}
	
	/* ¬ыводим паттерны с учЄтом add_pattern. */
	
	for (i=0;i<=max_used_p+add_pattern;i++,p_offset+=4)
	{
		fpos_t b,c;
		int p=i;       /* “екущий паттерн pt3-модул€. */
		byte it_rows;  /*  оличество строк в текущем it-паттерне (32-64). */
		byte comm_flag[3]={0,0,0}; /* ƒл€ каналов A,B,C (то есть дл€ каналов 1,2,3
		 в it-модуле) - признак, что в канале действует одна из команд Slide Up/Down,
		 Portamento или Vibrato. ≈сли признак установлен, то в it-модуле команда
		 будет ставитьс€ в следующих строках паттерна. “ип команды дл€ каждого из
		 трЄх каналов указываетс€ в comm_type (см. ниже), сразу в виде числа,
		 которым эта команда кодируетс€ в it-модуле. */
		byte comm_type[3];
		
		if (i>max_used_p) p=order[song_len-1];  /* ƒополнительный паттерн. */
		
		/* «аписываем в нужное место (p_offset) смещение текущего паттерна (но
		 если паттерн не используетс€, то там остаЄтс€ 0). */
		
		if (used_p[p]==0) continue;
		
		fgetpos_1 (f_it,&b);
		fsetpos_1 (f_it,&p_offset);
		fputc_1 (b,f_it);
		fputc_1 (b>>8,f_it);
		fputc_1 (b>>16,f_it);
		fputc_1 (b>>24,f_it);
		fsetpos_1 (f_it,&b);
		
		/* ѕерекодируем паттерн в текст. */
		
		clear_p ();
//		byte qw;
//		byte qe;
		a=getb_pt3(103)+(getb_pt3(104)<<8)+p*6; /* —мещение информации о паттерне. */
//    	qw=getb_pt3(103);
//		qe=(getb_pt3(104));
//		qe=(qe<<8);
//		qe=qe; /* —мещение информации о паттерне. */
//		a=qw+qe+p*6; /* —мещение информации о паттерне. */
		for (j=0;j<3;j++)
		{
			p_rows=convert_p((getb_pt3(a+1)<<8)+getb_pt3(a),j);
			a+=2;
		}
		
		/* «аписываем 8-байтный заголовок паттерна. */
		
		fputc_1 (0,f_it);  /* ƒлина (запишем потом). */
		fputc_1 (0,f_it);
		
		/*  ол-во строк (если меньше 32 - будет 32). */
		it_rows=p_rows; if (it_rows<32) it_rows=32;
		fputc_1 (it_rows,f_it);
		fputc_1 (0,f_it);
		
		fputc_1 (0,f_it);         /* Unused */
		fputc_1 (0,f_it);
		fputc_1 (0,f_it);
		fputc_1 (0,f_it);
		
		/* «аписываем содержимое паттерна. */
		
		for (j=0;j<it_rows;j++)  /* ÷икл по строкам. */
		{
			/* ≈сли в строке содержитс€ команда изменени€ Tempo - 0xB - или несколько
			 таких команд, то они преврат€тс€ в одну команду изменени€ Speed
			 в четвЄртом канале формируемого it-паттерна. */
			
			byte flag_tempo=((pattern[j].channel[0].command[0]==0xB)||
							 (pattern[j].channel[1].command[0]==0xB)||
							 (pattern[j].channel[2].command[0]==0xB));
			
			/* ≈сли it-паттерн оказалс€ удлинЄн до 32 строк и сейчас записываем
			 последнюю строку фактического pt3-паттерна, то в первом свободном
			 канале этой строки необходимо поставить команду C00.  */
			
			byte flag=((p_rows<it_rows)&&(j==(p_rows-1)));
			
			/* ≈сли сейчас записываем дополнительный паттерн, и записываетс€ его
			 последн€€ строка, то в первом свободном канале этой строки необходимо
			 поставить команду зацикливани€. ≈сли дополнительного паттерна нет и
			 сейчас записываетс€ паттерн, который стоит последним в списке позиций,
			 и записываетс€ его последн€€ строка, то в первом свободном канале этой
			 строки необходимо поставить команду зацикливани€. */
			
			byte flag_loop=(j==(p_rows-1))&&
			((i>max_used_p)||
			 ((add_pattern==0)&&(i==order[song_len-1])));
			
			if (flag_loop) flag=0; /*  оманда зацикливани€ отмен€ет наход€щуюс€
			 на той же строке команду "конец паттерна". */
			
			/* ≈сли сейчас записываем первую строку, уже не относ€щуюс€ к исходному
			 pt3-паттерну, то надо обнулить флаги продолжающихс€ команд во всех
			 каналах. */
			
			if (j==p_rows)
			{
				comm_flag[0]=0;
				comm_flag[1]=0;
				comm_flag[2]=0;
			}
			
			for (k=0;k<3;k++)       /* ÷икл по столбцам (каналам). */
			{
				byte note=pattern[j].channel[k].note;
				byte sample=pattern[j].channel[k].sample;
				byte volume=pattern[j].channel[k].volume;
				byte command=pattern[j].channel[k].command[0];
				byte command_d=pattern[j].channel[k].command[1];
				byte command_v=(pattern[j].channel[k].command[2]<<4)+
				pattern[j].channel[k].command[3];
				byte mv=0;  /* Maskvariable */
				
				if (note!=0) {mv|=1; comm_flag[k]=0;}
				if (sample!=0) mv|=2;
				if (volume!=0) mv|=4;
				if ((command==1)||(command==2)||(command==3)||(command==6))
				{
					comm_flag[k]=0;
					mv|=8;
				}
				
				/* —ледующие команды не конвертируютс€ ни в какую команду, но
				 останавливают действие предыдущих команд 1dxx, 2dxx, 3dxx, 60xy:
				 - 1dxx, если d и/или xx = 0,
				 - 2dxx, если d=0 (xx в этой команде не может равн€тьс€ нулю из-за
				 особенности формата pt3-модулей),
				 - 3dxx, если d и/или xx = 0,
				 - 60xy, если y=0. */
				
				if (((command==1)&&((command_d==0)||(command_v==0)))||
					((command==2)&&(command_d==0))||
					((command==3)&&((command_d==0)||(command_v==0)))||
					((command==6)&&((command_v&0xF0)==0))) mv-=8;
				
				if (flag||flag_loop) mv|=8;
				if (comm_flag[k]) mv|=8;
				if (mv==0) continue;         /* ѕусто. */
				fputc_1 (0x80+k+1,f_it);
				fputc_1 (mv,f_it);
				if (note!=0)
				{
					if (note==255) fputc_1 (254,f_it);  /* Note Cut */
					else fputc_1 (note+11,f_it);
				}
				if (sample!=0) fputc_1 (sample,f_it);
				if (volume!=0) fputc_1 (vol_tab[volume],f_it);
				if (command==1)    /* Slide Down (Exx). */
				{
					if ((command_d==0)||(command_v==0)) goto m1;
					if (command_v>0xDF) command_v=0xDF;
					fputc_1 ('E'-'A'+1,f_it);
					fputc_1 (command_v,f_it);
					comm_flag[k]=1;
					comm_type[k]='E'-'A'+1;
					continue;
				}
				if (command==2)    /* Slide Up (Fxx). */
				{
					if (command_d==0) goto m1;
					if (command_v>0xDF) command_v=0xDF;
					fputc_1 ('F'-'A'+1,f_it);
					fputc_1 (command_v,f_it);
					comm_flag[k]=1;
					comm_type[k]='F'-'A'+1;
					continue;
				}
				if (command==3)    /* Tone Portamento (Gxx). */
				{
					if ((command_d==0)||(command_v==0)) goto m1;
					fputc_1 ('G'-'A'+1,f_it);
					fputc_1 (command_v,f_it);
					comm_flag[k]=1;
					comm_type[k]='G'-'A'+1;
					continue;
				}
				if (command==6)    /* Vibrato in PT3 -> Tremor in IT (Ixx). */
				{
					if ((command_v&0xF0)==0) goto m1;
					fputc_1 ('I'-'A'+1,f_it);
					fputc_1 (command_v,f_it);
					comm_flag[k]=1;
					comm_type[k]='I'-'A'+1;
					continue;
				}
				if (comm_flag[k])
				{
					fputc_1 (comm_type[k],f_it);
					fputc_1 (0,f_it);
					continue;
				}
			m1: if (flag_loop)
			{
				fputc_1 ('B'-'A'+1,f_it);
				fputc_1 (getb_pt3(102),f_it);
				flag_loop=0;
				continue;
			}
				if (flag)
				{
					fputc_1 ('C'-'A'+1,f_it);
					fputc_1 (0,f_it);
					flag=0;
					continue;
				}
			}
			
			/* ≈сли надо (т.е. если flag_tempo=1), устанавливаем в 4-м канале
			 команду Speed=xx. */
			/* Tempo in PT3 -> Speed in IT (Axx). */
			
			if (flag_tempo)
			{
				byte a;
				
				fputc_1 (0x84,f_it);
				fputc_1 (8,f_it);
				
				for (k=0;k<3;k++)
				{
					byte command=pattern[j].channel[k].command[0];
					byte command_v=(pattern[j].channel[k].command[2]<<4)+
					pattern[j].channel[k].command[3];
					if (command==0xB) a=command_v;
				}
				
				fputc_1 ('A'-'A'+1,f_it);
				if (a==0) pt3_err();  /* «начение 0 недопустимо! */
				fputc_1 (a,f_it);
			}
			
			/* ≈сли флаг "установить команду зацикливани€ или перехода к другой
			 позиции" всЄ ещЄ установлен - значит, во всех трЄх каналах уже сто€т
			 команды. ¬ этом случае ставим команду в четвЄртом канале (или в
			 п€том, если четвЄртый зан€т, т.е. если flag_tempo=1). */
			
			if (flag_loop)
			{
				fputc_1 (0x84+flag_tempo,f_it);
				fputc_1 (8,f_it);
				fputc_1 ('B'-'A'+1,f_it);
				fputc_1 (getb_pt3(102),f_it);
			}
			if (flag)
			{
				fputc_1 (0x84+flag_tempo,f_it);
				fputc_1 (8,f_it);
				fputc_1 ('C'-'A'+1,f_it);
				fputc_1 (0,f_it);
			}
			fputc_1 (0,f_it); /*  онец строки. */
		}
		
		/* “еперь возвращаемс€ к заголовку (смещение начала заголовка сейчас в b)
		 и записываем длину (без учЄта заголовка). */
		
		fgetpos_1 (f_it,&c);
		fsetpos_1 (f_it,&b);
		fputc_1 (c-b-8,f_it);
		fputc_1 ((c-b-8)>>8,f_it);
		fsetpos_1 (f_it,&c);
	}
	
	fclose_1(f_it);
}

/* ==========================================================================
 ‘ункци€ make_txt - формирование txt-файла.
 ¬ход: name - им€ файла.
 ========================================================================= */

void make_txt (char* name)
{
	f_txt=fopen_1(name,"wb");
	
	/* ¬ывод названи€ модул€, сведений об авторе, информации о редакторе. */
	
	if (fprintf(f_txt,"Music: %s\r\n   by: %s\r\n\r\nEditor: ",name_pt3,
				author_pt3)==EOF) w_err();
	
	if (pt3_id==0) /* ћодуль создан в Pro Tracker 3. */
	{
		if (fprintf(f_txt,"%s%c","Pro Tracker 3.",getb_pt3(13))==EOF) w_err();
	}
	else           /* ћодуль создан в Vortex Tracker II. */
	{
		if (fwrite(module_pt3,(size_t)22,(size_t)1,f_txt)!=1) w_err();
	}
	
	/* ¬ывод информации о частотной таблице. */
	
	{
		char s0[]="Pro Tracker";
		char s1[]="Sound Tracker";
		char s2[]="ASM or PSC";
		char s3[]="Real Sound";
		char sx[]="unknown";
		char* s;
		
		switch (getb_pt3(99))
		{
			case 0: s=s0; break;
			case 1: s=s1; break;
			case 2: s=s2; break;
			case 3: s=s3; break;
			default: s=sx;
		}
		
		if (fprintf(f_txt,"\r\nFrequence table: %s\r\n",s)==EOF) w_err();
	}
	
	/* ¬ывод Tempo. */
	
	if (fprintf(f_txt,"Tempo: %u\r\n\r\n",getb_pt3(100))==EOF) w_err();
	
	/* ¬ывод списка позиций. */
	
	if (fprintf(f_txt,"Positions list\r\n\r\n")==EOF) w_err();
	for (i=0;i<song_len;i++)
	{
		char c=' ';
		byte p=getb_pt3(201+i)/3;
		if (i>=song_loop) c='*';
		if (fprintf(f_txt,"%02d %c %02X hex (%02d dec)\r\n",i,c,p,p)==EOF) w_err();
	}
	
	/* ¬ывод всех используемых паттернов. */
	
	for (i=0;i<=max_used_p;i++)
	{
		if (used_p[i]==0) continue;
		if (fprintf(f_txt,"\r\nPattern %X hex (%d dec)\r\n\r\n",i,i)==EOF) w_err();
		clear_p ();
		a=getb_pt3(103)+(getb_pt3(104)<<8)+i*6; /* —мещение информации о паттерне. */
		for (j=0;j<3;j++)
		{
			p_rows=convert_p((getb_pt3(a+1)<<8)+getb_pt3(a),j);
			a+=2;
		}
		out_p (p_rows,f_txt);
	}
	
	/* ¬ывод всех используемых сэмплов (их смещение не равно нулю), исключа€
	 нулевой сэмпл (отсутствие сэмпла). */
	
	for (i=1;i<32;i++)
	{
		char c='0'+i;
		byte smp_len;  /* ƒлина сэмпла. */
		byte smp_loop; /* Ќачало зацикленного участка сэмпла. */
		a=getb_pt3(105+i*2)+(getb_pt3(105+i*2+1)<<8); /* —мещение до данных
		 сэмпла. */
		if (a==0) continue;
		if (i>9) c='A'+i-10;  /* —эмплы 10-31 обозначаютс€ буквами A-V. */
		
		if (fprintf(f_txt,"\r\nSample %c (%d dec)\r\n\r\n",c,i)==EOF) w_err();
		
		smp_loop=getb_pt3(a);
		smp_len=getb_pt3(a+1);
		
		for (j=0;j<smp_len;j++)
		{
			byte s_0=getb_pt3(a+2+j*4);
			byte s_1=getb_pt3(a+2+j*4+1);
			short int t_offset=getb_pt3(a+2+j*4+2)+(getb_pt3(a+2+j*4+3)<<8);
			byte vol=s_1&15;
			char vol_s[16];
			byte noise_offset=(s_0>>1)&31;
			char add_vtn[4];
			char mask[4];
			char c=' ';
			
			if (j>=smp_loop) c='*';
			
			if ((s_0&0x80)==0) add_vtn[0]='0';
			else {if (s_0&0x40) add_vtn[0]='+'; else add_vtn[0]='-';}
			if (s_1&0x40) add_vtn[1]='+'; else add_vtn[1]='0';
			if (s_1&0x20) add_vtn[2]='+'; else add_vtn[2]='0';
			add_vtn[3]=0;
			
			if (s_1&0x10) mask[0]='-'; else mask[0]='T';
			if (s_1&0x80) mask[1]='-'; else mask[1]='N';
			if (s_0&1) mask[2]='-'; else mask[2]='E';
			mask[3]=0;
			
			for (k=0;k<15;k++)
			{
				if (vol>k) vol_s[k]='#'; else vol_s[k]='.';
			}
			vol_s[15]=0;
			
			if (fprintf(f_txt,"%02d %c %s %+05d %02d %s %s %X\r\n",j,c,add_vtn,
						-t_offset,noise_offset,mask,vol_s,vol)==EOF) w_err();
		}
	}
	
	/* ¬ывод всех используемых орнаментов (их смещение не равно нулю),
	 исключа€ нулевой орнамент (отсутствие орнамента). */
	
	for (i=1;i<16;i++)
	{
		byte orn_len;  /* ƒлина орнамента. */
		byte orn_loop; /* Ќачало зацикленного участка орнамента. */
		
		a=getb_pt3(169+i*2)+(getb_pt3(169+i*2+1)<<8); /* —мещение до данных
		 орнамента. */
		if (a==0) continue;
		if (fprintf(f_txt,"\r\nOrnament %X hex (%d dec)\r\n\r\n",i,i)==EOF) w_err();
		orn_loop=getb_pt3(a);
		orn_len=getb_pt3(a+1);
		for (j=0;j<orn_len;j++)
		{
			char c=' ';
			if (j>=orn_loop) c='*';
			if (fprintf(f_txt,"%02d %c %+03d\r\n",j,c,(signed char)getb_pt3(a+2+j))==EOF)
				w_err();
		}
	}
	
	fclose_1(f_txt);
}


/* ==========================================================================
 ‘ункци€ move_32bytes берЄт из модул€ по указанному смещению строку
 длиной 32 байта (название модул€ или сведени€ об авторе) и копирует еЄ
 в указанную строковую переменную. ѕри этом нулевые байты в исходной строке
 замен€ютс€ на пробелы, а пробелы в конце строки, если они есть, отрезаютс€.
 ¬ход: src - адрес исходной строки,
 dst - куда копировать.
 ========================================================================= */

void move_32bytes (byte* src, byte* dst)
{
	char a;
	int i;
	int len=0;            /* ƒлина строки без учЄта пробелов в конце. */
	
	for (i=0;i<32;i++)
	{
		a=*(src+i);
		if (a==0) a=' ';
		if (a!=' ') len=i+1;
		*(dst+i)=a;
	}
	*(dst+len)=0;
}

/* ==========================================================================
 ‘ункци€ getb_pt3 - вз€ть байт по указанному смещению из наход€щегос€
 в буфере pt3-модул€. ѕроизводитс€ проверка допустимости смещени€.
 ¬ход: a - смещение в pt3-модуле.
 ¬ыход: байт, вз€тый по указанному смещению.
 ========================================================================= */

byte getb_pt3 (word a)
{
	if (a>=len_pt3) {
	printf("Out of buffer (incorrect work with offsets? %d \n)",a);	
	pt3_err();
	}
	return module_pt3[a];
}

/* ==========================================================================
 ‘ункци€ clear_p - очистка буфера pattern.
 ========================================================================= */

void clear_p ()
{
	int i,j,k;
	
	for (i=0;i<64;i++)
	{
		pattern[i].env=0;
		pattern[i].noise=0;
		for (j=0;j<3;j++)
		{
			pattern[i].channel[j].note=0;
			pattern[i].channel[j].sample=0;
			pattern[i].channel[j].env_type=0;
			pattern[i].channel[j].orn=0;
			pattern[i].channel[j].volume=0;
			for (k=0;k<4;k++)
			{
				pattern[i].channel[j].command[k]=0;
			}
		}
	}
}

/* ==========================================================================
 ‘ункци€ convert_p - извлечение из исходного pt3-модул€ данных об одном
 канале паттерна и помещение этих данных в буфер pattern.
 ¬ход: a - смещение данных канала в pt3-модуле,
 c - номер канала (0,1,2).
 ¬ыход: длина этого канала (а значит, и всего паттерна) в строках.
 ========================================================================= */

byte convert_p (word a, byte c)
{
	byte n_line=0;  /* Ќомер текущей строки. */
	byte n_eff;
	byte n_not_an;
	byte last_env_type;
	byte last_orn;
	byte b;
	
main_loop:
	b=getb_pt3(a++);
	if (b==0)
	{
		if (n_line==0) pt3_err ();  /* Ќе может быть 0 строк. */
		return (n_line);
	}
	
	/* ќбработка очередной строки. */
	
	n_eff=0;
	if (n_line>=64) pt3_err ();  /* Ќе может быть больше 64 строк. */
	
line:
	if ((b>=1)&&(b<=9))
	{
		n_eff=b;          /* «апомнили номер эффекта. */
		b=getb_pt3(a++);
		goto line;
	}
	
	if (b==0x10)
	{
		last_env_type=pattern[n_line].channel[c].env_type=0xF;
		pattern[n_line].channel[c].sample=getb_pt3(a++)/2;
		b=getb_pt3(a++);
		goto line;
	}
	
	if ((b&0xF0)==0x10)
	{
		word env;
		
		last_env_type=pattern[n_line].channel[c].env_type=b-0x11;
		env=getb_pt3(a++)<<8;
		env=env+getb_pt3(a++);
		pattern[n_line].env=env;
		pattern[n_line].channel[c].sample=getb_pt3(a++)/2;
		b=getb_pt3(a++);
		goto line;
	}
	
	if ((b>=0x20)&&(b<=0x3F))
	{
		if (c==1)  /* —мещение шума - только в канале B. */
		{
			int i;
			
			for (i=n_line;i<64;i++) pattern[i].noise=b-0x20;
		}
		b=getb_pt3(a++);
		goto line;
	}
	
	if ((b&0xF0)==0x40)
	{
		pattern[n_line].channel[c].env_type=last_env_type;
		last_orn=pattern[n_line].channel[c].orn=b&0xF;
		b=getb_pt3(a++);
		goto line;
	}
	
	if ((b>=0x50)&&(b<=0xAF))
	{
		pattern[n_line].channel[c].note=b-0x50+1;
		goto line_end;
	}
	
	if (b==0xB0)
	{
		last_env_type=pattern[n_line].channel[c].env_type=0xF;
		pattern[n_line].channel[c].orn=last_orn;
		b=getb_pt3(a++);
		goto line;
	}
	
	if (b==0xB1)
	{
		n_not_an=getb_pt3(a++);
		b=getb_pt3(a++);
		goto line;
	}
	
	if ((b&0xF0)==0xB0)
	{
		word env;
		
		last_env_type=pattern[n_line].channel[c].env_type=(b-1)&0xF;
		pattern[n_line].channel[c].orn=last_orn;
		env=getb_pt3(a++)<<8;
		env=env+getb_pt3(a++);
		pattern[n_line].env=env;
		b=getb_pt3(a++);
		goto line;
	}
	
	if (b==0xC0)
	{
		pattern[n_line].channel[c].note=255;  /* R-- */
		goto line_end;
	}
	
	if ((b&0xF0)==0xC0)
	{
		pattern[n_line].channel[c].volume=b&0xF;
		b=getb_pt3(a++);
		goto line;
	}
	
	if (b==0xD0) goto line_end;
	
	if ((b>=0xD1)&&(b<=0xEF))
	{
		pattern[n_line].channel[c].sample=b-0xD0;
		b=getb_pt3(a++);
		goto line;
	}
	
	if ((b&0xF0)==0xF0)
	{
		last_env_type=pattern[n_line].channel[c].env_type=0xF;
		last_orn=pattern[n_line].channel[c].orn=b&0xF;
		b=getb_pt3(a++);
		pattern[n_line].channel[c].sample=b/2;
		b=getb_pt3(a++);
		goto line;
	}
	
line_end:  /* »звлекаем параметры эффектов. */
	
	switch (n_eff)
	{
		case 0: break;
			
		case 1: {
            word delta;
			
            pattern[n_line].channel[c].command[1]=getb_pt3(a++); /* delay */
            delta=getb_pt3(a++);
            delta+=getb_pt3(a++)<<8;
            if (((int)delta)<0)
            {
				pattern[n_line].channel[c].command[0]=2;
				delta=-((int)delta);
            }
            else pattern[n_line].channel[c].command[0]=1;
            pattern[n_line].channel[c].command[2]=(delta&0xF0)>>4;
            pattern[n_line].channel[c].command[3]=delta&0xF;
            break;
		}
			
		case 2: {
            word delta;
			
            pattern[n_line].channel[c].command[1]=getb_pt3(a++); /* delay */
            a+=2;
            delta=getb_pt3(a++);
            delta+=getb_pt3(a++)<<8;
            if (((int)delta)<0) delta=-((int)delta);
            pattern[n_line].channel[c].command[0]=3;
            pattern[n_line].channel[c].command[2]=(delta&0xF0)>>4;
            pattern[n_line].channel[c].command[3]=delta&0xF;
            break;
		}
			
		case 3: {
            byte offset=getb_pt3(a++);
			
            pattern[n_line].channel[c].command[0]=4;
            pattern[n_line].channel[c].command[2]=(offset&0xF0)>>4;
            pattern[n_line].channel[c].command[3]=offset&0xF;
            break;
		}
			
		case 4: {
            byte offset=getb_pt3(a++);
			
            pattern[n_line].channel[c].command[0]=5;
            pattern[n_line].channel[c].command[2]=(offset&0xF0)>>4;
            pattern[n_line].channel[c].command[3]=offset&0xF;
            break;
		}
			
		case 5: {
            pattern[n_line].channel[c].command[0]=6;
            pattern[n_line].channel[c].command[2]=getb_pt3(a++)&0xF;
            pattern[n_line].channel[c].command[3]=getb_pt3(a++)&0xF;
            break;
		}
			
		case 6: break;
		case 7: break;
			
		case 8: {
            word delta;
			
            pattern[n_line].channel[c].command[1]=getb_pt3(a++); /* delay */
            delta=getb_pt3(a++);
            delta+=getb_pt3(a++)<<8;
            if (((int)delta)<0)
            {
				pattern[n_line].channel[c].command[0]=0xA;
				delta=-((int)delta);
            }
            else pattern[n_line].channel[c].command[0]=9;
            pattern[n_line].channel[c].command[2]=(delta&0xF0)>>4;
            pattern[n_line].channel[c].command[3]=delta&0xF;
            break;
		}
			
		case 9: {
            byte tempo=getb_pt3(a++);
			
            pattern[n_line].channel[c].command[0]=0xB;
            pattern[n_line].channel[c].command[2]=(tempo&0xF0)>>4;
            pattern[n_line].channel[c].command[3]=tempo&0xF;
		}
	}
	n_line+=n_not_an;
	goto main_loop;
}

/* ==========================================================================
 ‘ункци€ out_p - вывод паттерна в текстовом виде в файл.
 ¬ход: в буфере pattern - содержимое выводимого паттерна,
 p_rows - количество строк в этом паттерне (1-64),
 f - указатель на структуру данных, св€занную с файлом, в который
 записываетс€ информаци€.
 ========================================================================= */

void out_p (byte p_rows, FILE* f)
{
	int i,j,k;
	char s[5];
	
	for (i=0;i<p_rows;i++)
	{
		/* Ќомер строки. */
		if (fprintf(f,"%02d | ",i)==EOF) w_err();
		
		/* ѕериод огибающей. */
		
		s[0]=0;
		if (pattern[i].env!=0)
		{
			sprintf(s,"%X",pattern[i].env);
		}
		for (j=0;j<4-strlen(s);j++)
		{
			if (fprintf(f,".")==EOF) w_err();
		}
		if (fprintf(f,"%s | ",s)==EOF) w_err();
		
		/* —мещение периода шума. */
		
		s[0]=0;
		if (pattern[i].noise!=0)
		{
			sprintf(s,"%hX",pattern[i].noise);
		}
		for (j=0;j<2-strlen(s);j++)
		{
			if (fprintf(f,".")==EOF) w_err();
		}
		if (fprintf(f,"%s",s)==EOF) w_err();
		
		/*  аналы A,B,C. */
		
		for (j=0;j<3;j++)
		{
			byte n=pattern[i].channel[j].note;   /* Ќота. */
			
			if (fprintf(f," | ")==EOF) w_err();
			if (n==0)
			{
				if (fprintf (f,"--- ")==EOF) w_err();
			}
			else
			{
				if (n==255)
				{
					if (fprintf(f,"R-- ")==EOF) w_err();
				}
				else
				{
					static char notes[]="C-C#D-D#E-F-F#G-G#A-A#B-";
					if (fprintf(f,"%c%c%c ",notes[(n-1)%12*2],notes[(n-1)%12*2+1],
								'1'+(n-1)/12)==EOF) w_err();
				}
			}
			
			/* ѕараметры ноты. */
			
			n=pattern[i].channel[j].sample;
			if (n==0) /* 0 - нет сэмпла. */
			{
				if (fprintf(f,".")==EOF) w_err();
			}
			else
			{
				/* ѕервые 9 сэмплов обозначаютс€ цифрами от 1 до 9,
				 следующие - буквами от A до V. */
				if (n<=9) n=n-1+'1'; else n=n-10+'A';
				if (fprintf(f,"%c",n)==EOF) w_err();
			}
			
			n=pattern[i].channel[j].env_type;
			if (n==0)
			{
				if (fprintf(f,".")==EOF) w_err();
			}
			else
			{
				if (fprintf(f,"%X",n)==EOF) w_err();
			}
			
			n=pattern[i].channel[j].orn;
			if (n==0)
			{
				if (fprintf(f,".")==EOF) w_err();
			}
			else
			{
				if (fprintf(f,"%X",n)==EOF) w_err();
			}
			
			n=pattern[i].channel[j].volume;
			if (n==0)
			{
				if (fprintf(f,". ")==EOF) w_err();
			}
			else
			{
				if (fprintf(f,"%X ",n)==EOF) w_err();
			}
			
			/*  оманда. */
			
			for (k=0;k<4;k++)
			{
				if ((n=pattern[i].channel[j].command[k])==0)
				{
					if (fprintf(f,".")==EOF) w_err();
				}
				else
				{
					if (fprintf(f,"%hX",n)==EOF) w_err();
				}
			}
		}
		
		if (fprintf(f,"\r\n")==EOF) w_err();
	}
}

/* ==========================================================================
 Ќижеследующие функции в случае ошибки при их выполнении выдают
 соответствующее сообщение и прерывают выполнение программы.
 ========================================================================= */

FILE* fopen_1 (char* name, char* mode)
{
	FILE* f;
	char* s;
	char* s1="read";
	char* s2="write";
	char n[13];
	
	if ((strlen(name)>=3)&&(name[1]==':'))  /* ≈сли указан полный путь. */
	{
		if (set_dir(name,n)==1) goto m1;
		f=fopen(n,mode);
	}
	else
	{
		//if (setdisk(cur_path[0]-'A')<(cur_path[0]-'A')) goto m1;
		if (chdir(cur_path)!=0) goto m1;
		f=fopen(name,mode);
	}
	
	if (f==NULL)
	{
	m1: if (mode[0]=='r') s=s1; else s=s2;
		printf ("\nCan't open file \"%s\" for %s!\n\n",name,s);
		exit (1);
	}
	return (f);
}

void fclose_1 (FILE* f)
{
	if (fclose(f)==EOF) {printf ("\nClose error!\n\n"); exit (1);}
}

void fputc_1 (int c, FILE* f)
{
	if (fputc(c,f)==EOF) w_err();
}

void fgetpos_1 (FILE* f, fpos_t* pos)
{
	if (fgetpos(f,pos)!=0) w_err();
}

void fsetpos_1 (FILE* f, fpos_t* pos)
{
	if (fsetpos(f,pos)!=0) w_err();
}

void r_err ()
{
	printf ("\nRead error!\n\n"); exit (1);
}

void w_err ()
{
	printf ("\nWrite error!\n\n"); exit (1);
}

void pt3_err ()
{
	printf ("\nIncorrect pt3-file!\n\n"); exit (1);
}

void vol_err ()
{
	printf ("Error: incorrect volume table!\n\n"); exit(1);
}

/* ==========================================================================
 ‘ункци€ set_dir.
 ¬ход: s - строка с полным путЄм к файлу и именем файла (например,
 "c:\work\n.txt"), name - строка, куда надо поместить им€ файла.
 ¬ыход: каталог, в котором находитс€ файл, установлен текущим; им€ файла
 помещено в строку name; возвращаетс€ код завершени€: 0 - OK, 1 - ошибка.
 ========================================================================= */

int set_dir (char *s, char *name)
{
	int a,d,i;
	char path[128];
	
	/* –азбиваем строку s на путь к файлу (path) и им€ файла (name). */
	a=strlen(s)-1; /* »ндекс последнего символа строки. */
	/* ѕросматриваем строку от конца к началу, пока не найдЄм символ '\',
	 отдел€ющий путь к файлу от имени файла. */
	while (s[a]!='\\')
	{
		if (a==0) return (1); /* —имвол '\' не найден - ошибка! */
		a--;
	}
	
	/*  опируем путь к файлу в строку path. ѕоследний '\' не включаетс€, но если
	 путь получилс€ лишь из двух символов (т.е. им€ диска и двоеточие) - то
	 включаетс€. */
	
	for (i=0;i<a+(a==2);i++) path[i]=s[i];
	path[i]=0;
	
	/*  опируем им€ файла в строку name. */
	for (i=a+1; i<strlen(s); i++)
	{
		if ((i-a-1)==12) return (1); /* »м€ больше 12 символов. */
		name[i-a-1]=s[i];
	}
	name[i-a-1]=0;
	/* ¬ыбор диска. */
	if ((path[0]>='A')&&(path[0]<='Z')) d=path[0]-'A';
	if ((path[0]>='a')&&(path[0]<='z')) d=path[0]-'a';
	// a=setdisk(d); if (d>=a) return (1); /* ¬ыбран несуществующий диск. */
	/* ѕереходим в нужный каталог. */
	// a=chdir(path); if (a!=0) return (1);
	return (0);
}

/* ==========================================================================
 ‘ункци€ cmp_names.
 ¬ход:  s1 - им€ первого файла (возможно, с полным путЄм к нему),
 s2 - им€ второго файла (возможно, с полным путЄм к нему).
 ¬ыход: 0, если s1 и s2 указывают на один и тот же файл, 1 - в противном
 случае.
 ========================================================================= */

//int cmp_names (char* s1, char* s2)
//{
//	int s1_full=(strlen(s1)>=3)&&(s1[1]==':');
//	int s2_full=(strlen(s2)>=3)&&(s2[1]==':');
//	
//	/* ≈сли дл€ обоих файлов полные пути указаны или не указаны, то
//	 просто сравниваем s1 и s2 (без учЄта регистра букв).*/
//	
//	if (s1_full==s2_full) return stricmp(s1,s2);
//	
//	/* ƒл€ одного файла путь к нему не указан, а дл€ другого - указан.
//	 ѕреобразуем ситуацию к виду, когда путь не указан дл€ первого файла. */
//	
//	{
//		char* temp;
//		if (s1_full==1) {temp=s1; s1=s2; s2=temp;}
//	}
//	
//	if ((strlen(cur_path)+1+strlen(s1)==strlen(s2))&&
//		(memicmp(cur_path,s2,strlen(cur_path))==0)&&
//		(s2[strlen(cur_path)]=='\\')&&
//		(stricmp(s2+strlen(cur_path)+1,s1)==0)) return 0; else return 1;
//}

